/**
 * ShieldJS主类，定义了框架的一些主要属性及方法
 * @author Kevin Lv <donggongai@126.com>
 * @class
 * @version 2.1.0
 * @date 2019-1-25
 */
var ShieldJS = {
    /** ShieldJS的版本号
     @type String
     @const
     */
    version:"2.0",
    /**    键盘按键的值的常量
        @enum {int}
        @readonly
    */
    keyCode: {
        ENTER: 13, ESC: 27, END: 35, HOME: 36,
        SHIFT: 16, TAB: 9, BLANK: 32,
        LEFT: 37, RIGHT: 39, UP: 38, DOWN: 40,
        DELETE: 46, BACKSPACE:8
    }
    /**    框架内置的几种常用样式名
        @enum {String}
        @readonly
    */
    ,css:{
        TITLE:'viewTitle',WIDTH:'viewWidth',HEIGHT:'viewHeight',
        /** 显示 */
        SHOW:'shield-show',
        /** 选中*/
        THIS:'shield-this',
        /** 禁用 */
        DISABLED:'shield-disabled'
    }
    /**    框架核心方法 
     * @class ShieldJS.core */
    ,core:{}
    /**    框架html动作绑定方法 
     * @class ShieldJS.HtmlAction */
    ,HtmlAction:{}
    /**    框架消息模板
        @type Key-Value
        @final
     */
    ,_msg:{}
    /**    根据key及传入参数获取模板信息
        @param key {String} 内置消息模板的key
        @param args {Array(Object)} 替换模板变量的参数
        @returns {String} 替换参数后的模板信息  */
    ,msg : function(key, args){
        var _format = function(str,args) {
            args = args || [];
            var result = str || "";
            for (var i = 0; i < args.length; i++){
                result = result.replace(new RegExp("\\{" + i + "\\}", "g"), args[i]);
            }
            return result;
        }
        return _format(this._msg[key], args);
    }
    /**    内部变量设置（可设置是否调试模式）
     @enum {Boolean}
     @readonly    */
    ,_set:{
        /** 调试模式，部署时关闭 */
        debug:true 
    }
    /**    调试输出是否输出堆栈信息
        @param msg {Boolean} 是否输出堆栈信息
     */
    ,debugTrace : false
    /**    调试输出
        @param msg {String} 调试信息
        @param trace {Boolean} 输出堆栈信息
    */
    ,debug : function(msg, trace){
        if (this._set.debug) {
            if (typeof(console) != "undefined"){
                var logInfo = new Date()+" "+msg;
                if (trace || ShieldJS.debugTrace) {
                    logInfo += " by:" + printCallStack();
                }
                console.log(logInfo);
            } 
//            else alert(msg);
        }
    }
    ,console : function(msg){
        if (typeof(console) != "undefined"){
            var logInfo = new Date()+" "+msg;
            console.log(logInfo);
        } 
    }
    /**    错误输出
        @param msg {String} 错误信息
    */
    ,error : function(msg){
        this.alert("错误信息", msg, "error");
    }
    /**    设置ShieldJS的版本号
        @param suffix {String} 版本号后缀
     */
    ,setVersion: function(suffix) {
        if (this.version && this.version != "2.0") {
            alert("引入了多个shieldjs扩展包，版本号:"+this.version+" 与 "+suffix);
            return;
        }
        this.version = this.version+"-"+suffix;
    }
    /**    加载文件
        @param path {String} 文件路径
        @param success {Function} 加载成功后的回调方法
     */
    ,loadfile : function(path, success) { //加载文件
        var data = "";
        $.ajax({
            url: path,
            async: false, //同步
            data: {t:'2018011601'},
            success: function(content){
                // content就为文件的文本内容了,文件的编码最好保存成utf-8
                success(content);
            }
        });
    }
    /**    当前js文件的路径，通过{@link ShieldJS.getJsPath}获取
        @type String
        @see ShieldJS.getJsPath
    */
    ,jsPath :""
    /**    获取当前js文件的路径
     * @see {@link ShieldJS.jsPath}
     * @returns {String} 当前js文件的路径  */
    ,getJsPath : function() {
        if (!this.jsPath) {
            var js = document.scripts;
            this.jsPath = js[js.length-1].src.substring(0,js[js.length-1].src.lastIndexOf("/")+1);
        }
        return this.jsPath;
    }
    /**    提示框，可以覆盖，默认采用alert，type字符型（success、error、info、warning）
     * @param title {String} 标题
     * @param message {String} 提示内容
     * @param type {String} 提示类型包括：success、error、info、warning4种  */
    ,alert : function(title, message, type){ 
        alert(message);
    }
    /**    确认框
     * @param title {String} 标题
     * @param message {String} 提示内容
     * @param ok {String} 确定后的回调方法
     * @param cancel {String} 取消后的回调方法  */
    ,confirm : function(title, message, ok, cancel){ 
        if (confirm(message)) {
            ok();
        } else {
            cancel();
        }
    }
    /**    框架封装的ajax方法
     * @class ShieldJS.ajax */
    ,ajax : {
        /**    ajax请求对象 */
        requests : {
            singleRequest : null,
            mutiRequest : null,
            clearRequest : function() {
                this.singleRequest = null;
                this.mutiRequest = null;
            }
        },
        abortLastReq : function() {
            if (this.requests && this.requests.singleRequest) {
                this.requests.singleRequest.abort();
                this.requests.singleRequest = null;
                //ShieldJS.debug("abort ajax request");
            }
        },
        /**    ajax全局处理方法，可覆盖 */
        global : {
            error : function(response, textStatus, errorThrown) {
//                第一个参数 response（jqXHR ） 在jQuery1.5版本以后则开始使用jqXHR对象，该对象是一个超集，就是该对象不仅包括XMLHttpRequest对象，还包含其他更多的详细属性和信息
//                readyState :当前状态,0-未初始化，1-正在载入，2-已经载入，3-数据进行交互，4-完成。
//                status  ：返回的HTTP状态码，比如常见的404,500等错误代码。
//                statusText ：对应状态码的错误信息，比如404错误信息是not found,500是Internal Server Error。
//                responseText ：服务器响应返回的文本信息
//                第二个参数  textStatus（String）：返回的是字符串类型，表示返回的状态，根据服务器不同的错误可能返回下面这些信息："timeout"（超时）, "error"（错误）, "abort"(中止), "parsererror"（解析错误），还有可能返回空值。
//                第三个参数 errorThrown（String）：也是字符串类型，表示服务器抛出返回的错误信息，如果产生的是HTTP错误，那么返回的信息就是HTTP状态码对应的错误信息，比如404的Not Found,500错误的Internal Server Error。
                var responseText = response.responseText;
                ShieldJS.debug(responseText);
                var contentType = response.getResponseHeader("content-type") || "";
                ShieldJS.checkError(responseText, contentType);
                if (clickBtn) {
                    clickBtn.removeAttr('disabled');
                }
                if (ShieldJS.contentMainE.length > 0) {
                    ShieldJS.contentMainE.find(":button").prop("disabled", false);
                }
            },
            complete : function(response, textStatus) {
                ShieldJS.ajax.requests.clearRequest();
//                if (response.status == 200) {
//                }
                //不使用 findAndMarkEle 防止多加
                if (ShieldJS.contentMainE && ShieldJS.contentMainE.length > 0) {
                    ShieldJS.contentMainE.find("input[type=button],input[type=submit],input[type=reset]")
                        .not(".noclass,.ke-button").removeClass("button").addClass("button");
                    ShieldJS.contentMainE.find("button").not(".noclass").removeClass("button1").addClass("button1");
                }
                if (ShieldJS.avtiveTabContentE && ShieldJS.avtiveTabContentE.length > 0) { //tab内容区
                    ShieldJS.avtiveTabContentE.find("input[type=button],input[type=submit],input[type=reset]")
                        .not(".noclass,.ke-button").removeClass("button").addClass("button");
                    ShieldJS.avtiveTabContentE.find("button").not(".noclass").removeClass("button1").addClass("button1");
                }
                if (ShieldJS.dialogE && ShieldJS.dialogE.length > 0) { //弹出框
                    ShieldJS.dialogE.find("input[type=button],input[type=submit],input[type=reset]")
                        .not(".noclass,.ke-button").removeClass("button").addClass("button");
                    ShieldJS.dialogE.find("button").not(".noclass").removeClass("button1").addClass("button1");
                }
            }
        },
        dealParamsAjax : function(method, ele, url, params, success, error, dataType, async) {
            // shift arguments if data argument was omitted
            if (typeof(ele) == "string") {
                async = dataType;
                dataType = error;
                error = success;
                success = params;
                params = url;
                url = ele;
                ele = undefined;
            }
            return this.ajax(ele, url, params, success, error, method, dataType, async);
        },
        /**    ajax请求
         * @param ele {jQueryObj} 发起请求的jQuery对象
         * @param url {String} 请求链接
         * @param params {Object} 参数,json格式或者字符串格式
         * @param success {Function} 成功的回调方法，注意区别于ajax原生的success，该方法为后台返回的成功方法
         * @param error {Function} 失败的回调方法，注意区别于ajax原生的error，该方法为后台返回的失败方法
         * @param method {String} 请求方法
         * @param dataType {String} 返回结果类型
         * @param async {Boolean} 是否是异步请求 */
        ajax : function(ele, url, params, success, error, method, dataType, async) {
            if (typeof(ele) == "string") {
                async = dataType;
                dataType = error;
                error = success;
                success = params;
                params = url;
                url = ele;
                ele = undefined;
            }
            disabledBtn();
            if (!params) {
                params = {};
            }
            params.r = new Date().getTime();
            if (ele) {
                ele.html(ShieldJS.loadingHtml);
            }
            if (params.singleRequest) {
                this.abortLastReq();
            }
            if (async == null) {
                async = true;
            }
            var request = $.ajax({
                url : url,
                type: method,
                dataType: dataType,
                data : params,
                traditional : true,
                async : async, //异步(不写默认值ie下有问题)
                beforeSend:function(XMLHttpRequest){
                    var tokenEle = $("[id='csrfTokenInput']:last"); // #csrfTokenInput只能取一个
                    if (ShieldJS.contentMainE.find("iframe").length>0) { //如果有iframe则取iframe里的
                    	tokenEle = tokenEle.add(ShieldJS.contentMainE.find("iframe").contents().find(":root").find("[id='csrfTokenInput']:last"));
                    }
                    if (tokenEle.length > 0) {
                    	var tokenEle = tokenEle.last();
                        XMLHttpRequest.setRequestHeader(tokenEle[0].name, tokenEle.val());
                    }
                    // 显示遮罩层
                    //App.blockUI({target : ele,animate : true});
                },
                success : function(htmlData, textStatus, jqXHR) {
                    undisabledBtn();
                    if (clickBtn) {
                        clickBtn.removeAttr('disabled');
                    }
                    var contentType = jqXHR.getResponseHeader("content-type") || "";
                    if (ShieldJS.checkError(htmlData, contentType)) {
                        if (ele) {
                            ele.html(htmlData);
                        }
                        // initPage();// 初始化页面
                        if (typeof success == 'function') {
                            success(htmlData);
                        }
                    } else {
                        if (ele) {
                            ele.html('');
                        }
                        if (typeof error == 'function') {
                            error(htmlData);
                        }
                    }
                },
                complete:function(response, textStatus){
                    //请求结束方法增强处理  ,隐藏遮罩层
                    //App.unblockUI(ele);
                    ShieldJS.ajax.global.complete(response, textStatus);
                },
                error: function (response, textStatus, errorThrown) { 
                    ShieldJS.ajax.global.error(response, textStatus, errorThrown);
                }
            });
            if (params.mutiRequest) {
                this.requests.mutiRequest = request;
            } else { 
                this.requests.singleRequest = request;
            }
        },
        /**    ajax发起get请求
         * @param ele {jQueryObj} 发起请求的jQuery对象
         * @param url {String} 请求链接
         * @param params {Object} 参数,json格式或者字符串格式
         * @param success {Function} 成功的回调方法，注意区别于ajax原生的success，该方法为后台返回的成功方法
         * @param error {Function} 失败的回调方法，注意区别于ajax原生的error，该方法为后台返回的失败方法
         * @param dataType {String} 返回结果类型，参考jQuery的ajax说明
         * @param async {Boolean} 是否是异步请求 */
        get : function(ele, url, params, success, error, dataType, async) {
            this.dealParamsAjax("get", ele, url, params, success, error, dataType, async);
        }
        /**    ajax发起post请求
         * @param ele {jQueryObj} 发起请求的jQuery对象【非必需】
         * @param url {String} 请求链接
         * @param params {Object} 参数,json格式或者字符串格式
         * @param success {jQueryObj} 成功的回调方法，注意区别于ajax原生的success，该方法为后台返回的成功方法
         * @param error {jQueryObj} 失败的回调方法，注意区别于ajax原生的error，该方法为后台返回的失败方法
         * @param dataType {jQueryObj} 返回结果类型，参考jQuery的ajax说明
         * @param async {jQueryObj} 是否是异步请求 */
        ,post : function(ele, url, params, success, error, dataType, async) {
            this.dealParamsAjax("post", ele, url, params, success, error, dataType, async);
        }
        /**    ajax获取json对象
         * @param url {String} 请求链接
         * @param params {Object} 参数,json格式或者字符串格式
         * @param success {Function} 成功的回调方法，注意区别于ajax原生的success，该方法为后台返回的成功方法
         * @param error {Function} 失败的回调方法，注意区别于ajax原生的error，该方法为后台返回的失败方法
         * @param async {Boolean} 是否是异步请求 */
        ,getJSON : function(url, params, success, error, async) {
            this.dealParamsAjax("get", null, url, params, success, error, "json", async);
        }
    }
    ,dataExtends : {needLogin : false}
    /**    返回值统一方法，判断有无错误（TODO方法名待修改）
     * @param data {Object} 验证对象，可能为json对象也可能为html文本，json对象示例{"success":true,"message":"提示信息"}
     * @param contentType {String} 返回结果类型
     * @returns {Boolean} 验证通过时返回true，否则返回false */
    ,checkError : function(data, contentType) {
        // 为json格式
        var json;
        if (typeof data == 'object') { //js对象
            json = data;
        } else { //一般为string
            try {
                json = $.parseJSON(data);
            } catch (e) {
                json = '';
            }
        }
        if (json) {
            if (json.refresh) { //刷新
                $("[type='submit']").closest("form.searchForm").submit();
            }
            if (json.data && json.data.href && json.data.target && ShieldJS.contentMainE) { //含有附加内容,此处是链接
                ShieldJS.contentMainE.find(json.data.target).show().attr("href", json.data.href);
            }
            if (json.message && json.success) {
            	var title = "消息提示";
            	if (json.data && json.data.title) {
            		title = json.data.title;
                }
                ShieldJS.alert(title, json.message, "success");
            }
            if (json.success == false) { //失败
                var logintype = json.data&&json.data.logintype;
                if (logintype) {
                    if (logintype == 'redirect') {
                        window.location.href = json.data.loginurl;
                    } else if(logintype == 'reload') {
                        window.location.reload();
                    }else  {
                        ShieldJS.checkErrorLoginExtend(json, data);
                    }
                } else {
                    if (json.message && !json.success) {
                        ShieldJS.alert("消息提示", json.message, "error");
                    }
                }
                return false;
            }
        }
        return true;
    }
    /**    检查返回数据登录的扩展方法（子类可覆盖）
     * @param data {JSON} 返回的对象，一般为json格式
     * @param data {Object} 返回的原始对象，一般为string或者json格式
     * @returns {Boolean} 返回true继续执行后续方法，返回false则不再执行后续方法 */
    ,checkErrorLoginExtend : function(json, data) { //扩展方法
        if (!ShieldJS.dataExtends.needLogin) {
            ShieldJS.dataExtends.needLogin = true;
            ShieldJS.openDialog(json.data.loginurl, {}, function(ele, dialog) {
                ele.data("extendRemove", function(index){ //扩展弹出框的remove方法
                    ShieldJS.dataExtends.needLogin = false;
                });
                ShieldJS.form.initSubmit(ele, function(formE, targetE, data) {//成功后
                    dialog.remove(); //关闭弹出框
                    if (!ShieldJS.dialogE) { //非弹出框则只执行刷新
                        var searchForm = $("[type='submit']").closest("form.searchForm");
                        if (searchForm.length > 0) {
                            searchForm.submit();
                        } else {
                            ShieldJS.activeSiderE.click();
                        }
                    }
                });
            }, "登录", 400, 500, null, "iframe", {"onlyOne":true});
            if (json.message && !json.success) {
                ShieldJS.alert("消息提示", json.message, "error");
            }
        }
        return true;
    }
    /**    窗口resize的处理事件集合（使用时 winResizes["方法名"]=function）
        @type Key-Value
     */
    ,winResizes : {}
    /**    document点击的处理事件集合（使用时 docClicks["方法名"]=function）
        @type Key-Value
     */
    ,docClicks : {}
    /**    弹出层，依赖于layer js
     * @constructor ShieldJS.dialog
     * @example  示例：
     * var dialog = new ShieldJS.dialog();
     * dialog.index = 1;
     * dialog.remove(); */
    ,dialog : {
        /**    弹出框元素对象
            @type jQueryObject
         */
        dialogO : null,
        init : function (ele, index, title, width, height, preEle, preEleIndex, onlyOne){
            var dialog = new Dialog();
            dialog.init(ele, index, width, height, preEle, preEleIndex);
            dialog.title = title;
            this.dialogO = dialog;
            ShieldJS.dialogs.put(index, dialog);
        },
        /**    移除弹出框 */
        remove : function (indexV, callback){
            var dialogIndex = this.dialogO.index;
            if (indexV) {
                dialogIndex = indexV;
            }
            var dialogObj = ShieldJS.dialogs.get(dialogIndex);
            ShieldJS.winResizes["dialogResize"+dialogIndex] = null; //resize置空
            var curDialogE = ShieldJS.dialogE;
            if (curDialogE.data("extendRemove")) {
                curDialogE.data("extendRemove")(indexV);
            }
            ShieldJS.dialog.removeCallback(curDialogE);
            console.log(new Date()+"remove dialog"+" "+dialogIndex);
            if (dialogObj) {
                ShieldJS.dialogE = dialogObj.preEle;
                var index = dialogObj.preEleIndex;
                var perDialog = ShieldJS.dialogs.get(index);
                this.dialogO = perDialog;
            } else {
                ShieldJS.dialogE = null;
                this.index = -1;
            }
            if (dialogObj && dialogObj.index) {
                ShieldJS.dialogs.remove(dialogObj.index);
                layer.close(dialogObj.index); //此时你只需要把获得的index，轻轻地赋予layer.close即可
            } else {
                ShieldJS.dialogs.remove(layer.index);
                layer.close(layer.index); //它获取的始终是最新弹出的某个层，值是由layer内部动态递增计算的
            }
        },
        removeCallback : function(dialogE) {
            // 具体实现中扩展
        },
        /**    重置宽高
         * @type jQueryObject */
        resize : function(layerIndex, layerInitWidth, layerInitHeight) {
            if (!layerInitWidth) {
                var perDialog = ShieldJS.dialogs.get(layerIndex);
                if (perDialog && perDialog.ele) {
                    layerInitWidth = perDialog.ele.width(); //获取元素的宽度
                }
            }
            var docWidth = $(window).width(); //可视区域，document为全部区域
            var docHeight = $(window).height(); //可视区域，document为全部区域
            var minWidth = layerInitWidth > docWidth ? docWidth : layerInitWidth;  
            var minHeight = layerInitHeight > docHeight ? docHeight : layerInitHeight;
//            console.log("resize"+layerIndex+" "+layerInitWidth+" "+ layerInitHeight+" "+docWidth+" "+docHeight);
            var style = {height:layerInitHeight, width: layerInitWidth};
            if (layerInitHeight > docHeight) {
                style.top = 5;
                style.height = minHeight -10;
            } else if (layerInitWidth > docWidth) {
                style.width = minWidth;
            }
            this.width = style.width;
            this.heigth = style.height;
            layer.style(layerIndex, style);
        },
        /**    打开弹出框
         * @param url {String} 弹出框的链接
         * @param params {Object} 参数,json格式或者字符串格式
         * @param callback {Function} 打开弹出框后的回调
         * @param title {String} 弹出框标题
         * @param width {Number} 弹出框宽度
         * @param height {Number} 弹出框高度
         * @param async {Boolean} 是否异步
         * @param relType {String} 关联类型，可以为iframe或者不填
         * @param options {Json} 扩展属性
         */
        open : function(url, params, callback, title, width, height, async, relType, options) {
            params.singleRequest = true; //单个请求
            var dialog= this;
            var onlyOne = options.onlyOne||false;
//            try {
//                layer;
//            } catch (e) {
//                ShieldJS.error("缺少依赖JS库：layer！");
//                return false;
//            }
            if(typeof layer == "undefined" ){
                ShieldJS.error("缺少依赖JS库：layer！");
                return false;
            }
            
            var openType = 1;
            if (relType && relType=="iframe") {
                openType = 2;
            }
            if (openType == 2) { //iframe
                var index = layer.open({
                    //可传入的值有：0（信息框，默认）1（页面层）2（iframe层,content位url）3（加载层）4（tips层）
                    type:2,
                    skin: 'shieldjs-custom-layer', //加上边框layui-layer-rim
                    title: title,
                    area: [width+'px', height+'px'],
                    fix: false, //不固定
                    shadeClose: false,
                    shade: 0.5,
                    scrollbar: false,
                    content: url,
                    success: function(layero, index) {
                        layer.iframeAuto(index); //高度自适应
                        /*windows窗口变化时重置大小,经测试放到外面会有延时，影响展示效果 */
                        ShieldJS.winResizes["dialogResize"+index] = function() {
                            layer.iframeAuto(index); //高度自适应
                        };
                        setTimeout(function(){
                            dialog.dialogO.ele = $('#layui-layer'+index).find("iframe").contents().find(":root"); //搜索根元素
                            ShieldJS.dialogE = dialog.dialogO.ele;
                            if (callback) {
                                callback(dialog.dialogO.ele, dialog);
                            }
                            if (ShieldJS.core) {
                                ShieldJS.core.bindHtmlAction(dialog.dialogO.ele, null, null, options.searchForm, dialog); //内部继续加载
                            }
                            dialog.width = layero.width();
                            dialog.height = layero.height();
                        }, 200);
                    },
                    cancel: function(index, layero){
                        dialog.remove();
                        return true; 
                    }
                });
                dialog.init($('#layui-layer'+index), index, title, width, height, ShieldJS.dialogE, dialog.dialogO?dialog.dialogO.index:null, onlyOne); //初始化
                ShieldJS.dialogE = dialog.dialogO.ele;
//                $('#layui-layer'+index).find("iframe").load(function() { //iframe加载完成后
//                    dialog.dialogO.ele = $(this).contents().find(":root"); //搜索根元素
//                    ShieldJS.dialogE = dialog.dialogO.ele;
//                    if (callback) {
//                        callback(dialog.dialogO.ele, dialog);
//                    }
//                    ShieldJS.core.bindHtmlAction(dialog.dialogO.ele, null, null, null, dialog); //内部继续加载
//                    dialog.width = $(this).width();
//                    dialog.height = $(this).height();
//                });
                
            } else {
                ShieldJS.ajax.get(url, params, function(data) {
                    var winHeight = $(window).height();
                    var index = layer.open({
                        type: openType,
//                        moveOut: true,
//                        maxmin: true,
                        skin: 'shieldjs-custom-layer', //加上边框layui-layer-rim
                        maxHeight : winHeight-14, //最大高度，只有当高度自适应时，设定才有效。
                        area: (width ? width : 500)+'px', //宽度
                        title : title,
                        content: data.replace(/(^\s*)|(\s*$)/g, ""),
                        success: function(layero, index) {
                            /*setTimeout(function(){ //延时更新窗口大小，防止有其他元素更改高度宽度
                                var layerIndex = index; //获取当前窗口的索引
                                var layerInitWidth = $("#layui-layer"+index).width(); //获取layer的宽度
                                var layerInitHeight = $("#layui-layer"+index).height(); //获取layer的高度
                                dialog.width = layerInitWidth;
                                dialog.height = layerInitHeight;
                                ShieldJS.dialog.resize(layerIndex, layerInitWidth, layerInitHeight); //调用resizeLayer方法 
                            }, 200);*/
                            setTimeout(function(){
                                if (callback) {
                                    callback(dialog.dialogO.ele, dialog, index);
                                }
                                if (ShieldJS.core.bindHtmlAction) {
                                    ShieldJS.core.bindHtmlAction(dialog.dialogO.ele, null, null, null, dialog); //内部继续加载
                                }
                            }, 200);
                        },
                        cancel: function(index, layero){
                            dialog.remove();
                            return true; 
                        }   
                    });
                    dialog.init($('#layui-layer'+index), index, title, null, null, ShieldJS.dialogE, dialog.dialogO?dialog.dialogO.index:null, onlyOne); //初始化
                    ShieldJS.dialogE = dialog.dialogO.ele;
                    
                    var dialogContentE = dialog.dialogO.ele.find(".layui-layer-content");
                    var titleHeight = dialog.dialogO.ele.find(".layui-layer-title").height();
                    /*自身内容发生变化时，layui-layer-content为dialog的内容区*/
                    dialogContentE.resize(function() {
                        console.log(dialogContentE[0].scrollHeight+titleHeight);
                        setTimeout(function(){
                            dialog.resize(index, null, dialogContentE[0].scrollHeight+titleHeight); //调用resize方法
                        }, 100);    
                    });
                        
                        
                    /*windows窗口变化时重置大小*/
                    ShieldJS.winResizes["dialogResize"+index] = function() { //宽度处理有问题
//                        console.log("resize"+index+" "+dialog.dialogO.ele.width()+" "+ dialog.dialogO.ele.height()+" scroll:"+ dialog.dialogO.ele.find(".layui-layer-content")[0].scrollHeight );
                        // ShieldJS.dialogE.find(".layui-layer-content")[0].scrollHeight 为div的实际高度，如有滚动条时获取真实高度
                        dialog.resize(index, null, dialogContentE[0].scrollHeight+titleHeight); //调用resize方法 
                    };
                    
                }, function(data) {
                    var json;
                    if (typeof data == 'object') { //js对象
                        json = data;
                    } else { //一般为string
                        try {
                            json = $.parseJSON(data);
                        } catch (e) {
                            json = '';
                        }
                    }
                    ShieldJS.error(json.message||"打开弹出框出错！" + url + " params: "+params);
                }, null, async);
            }
        }
    }
    /**    弹出框Map,key为下标，value为dialog对象
        @type Map
     */
    ,dialogs : new Map()
    /**    打开弹出框(实际调用的是dialog.open)
     * @param url {String} 弹出框的链接
     * @param params {Object} 参数,json格式或者字符串格式
     * @param callback {Function} 打开弹出框后的回调
     * @param title {String} 弹出框标题
     * @param width {Number} 弹出框宽度
     * @param height {Number} 弹出框高度
     * @param async {Boolean} 是否异步
     * @param relType {String} 关联类型，可以为iframe或者不填
     * @param options {Json} 扩展属性
     */
    ,openDialog : function(url, params, callback, title, width, height, async, relType, options) {
        options = options||{};
        ShieldJS.dialog.open(url, params, callback, title, width, height, async, relType, options);
    }
    ,getDialogs : function(title) {
        var dialogsGet = new Array();
        for(var dialog in ShieldJS.dialogs.values()){
            if (dialog.title == title) {
                dialogsGet.push(dialog); //添加到 dialogsGet 的尾部
            }
        }
        return dialogsGet;
    }
    /**    框架的form处理
     * @constructor ShieldJS.form */
    ,form : {
        /**    初始化当前元素的表单
         * @param ele {jQueryObj} 需要处理的jQuery对象
         * @param callback {Function} 表单提交后的回调 (formE, targetE, data)
         * @param checkFn {Function} 对表单进行检查筛选，返回true表示通过
         */
        initSubmit : function(ele, callback, checkFn) {
            var ShieldJSForm = this;
            if (ele.length > 0) {
                var formEs = (ele[0].tagName != 'FORM') ? ele.find('form') : ele;
                formEs.each(function(i, n) {
                    ShieldJSForm.initOneSubmit($(this), callback, checkFn);
                });
            }
        },
        /**    初始化单个表单
         * @param formE {jQueryObj} form标签的jQuery格式对象
         * @param callback {Function} 表单提交后的回调
         * @param checkFn {Function} 对表单进行检查筛选，返回true表示通过
         */
        initOneSubmit : function(formE, callback, checkFn) {
            //_blank 打开新窗口的不处理
            var target = "";
            if(hasAttr(formE,"target")){
                target = formE.attr("target");
            }
            if (target != "_blank") {
                formE.unbind('submit').submit(function() {
                    if(!target){
                        target = formE.attr('shieldTarget'); //shieldJs
                    }
                    var targetE = target ? findEle(formE, target) : null; //修改
                    if (targetE && targetE.length == 0) {
                        targetE = target ? $(target) : null; //修改
                        if (targetE.length > 1) {
                            ShieldJS.error("表单提交目标对象超过1个，不执行覆盖操作！target: "+target + " 数目："+targetE.length);
                            targetE = null;
                        }
                    }
                    clickBtn = formE.find(':submit,.shieldSubmit');
                    if (!clickBtn.is(':disabled')) {
                        
                        var formTemp = [];
                        var options = {
                                beforeSubmit : function() {
                                    if (ShieldJS.form.validate(formE)) {
                                        if ((typeof checkFn != 'function' || checkFn(formE))) {
                                            if (targetE) {
                                                targetE.html(ShieldJS.loadingHtml);
                                            }
                                            // 防止重复提交
                                            clickBtn.attr('disabled', 'disabled');
                                            
                                            // 清除嵌套表单
                                            formE.find('form').each(function() {
                                                var formE = $(this);
                                                formTemp.push([ formE.prev(), formE ]);
                                                formE.remove();
                                            });
                                            
                                            return true;
                                        }
                                    }
                                    
                                    return false;
                                },
                                success : function(data, textStatus, jqXHR) {
                                    clickBtn.removeAttr('disabled');
                                    var contentType = jqXHR.getResponseHeader("content-type") || "";
                                    if (ShieldJS.checkError(data, contentType)) { //检查是否成功
                                        if (targetE) {
                                            targetE.html(data);
                                        }
                                        if (typeof callback == 'function') { //成功后的回调
                                            callback(formE, targetE, data);
                                        }
                                        if (typeof formE.attr("callback") != 'undefined') {
                                            var method = formE.attr("callback");
                                            if($.isFunction(methods[method])){
                                                methods[method](targetE);
                                            }
                                        }
                                    }
                                    
                                    // 还原嵌套表单
                                    for ( var i = 0; i < formTemp.length; i++) {
                                        var obj = formTemp[i];
                                        if (obj[0].append) {
                                            obj[0].after(obj[1]);
                                        }
                                    }
                                }
                        };
                        setTimeout(function() {
                            formE.ajaxSubmit(options);
                        }, 1);
                        
                    }
                    return false;
                });
            }
            this.initOneSubmitExtend(formE, target);
        },
        /**    初始化单个表单的扩展方法（默认将当前页码设置为1）
         * @param formE {jQueryObj} form标签的jQuery格式对象
         * @param target {String} 表单提交后目标对象
         */
        initOneSubmitExtend : function(formE, target) { //扩展方法
            formE.find(":submit").click(function() { //执行查询时把页数设置为1
                var pageNum = formE.find(".pageNum");
                if (pageNum.length > 0) {
                    pageNum.val(1);
                }
            });
        },
        /**    表单验证
         * @param formE {jQueryObj} 待验证的form对象
         * @returns {Boolean} 验证通过时返回true，否则返回false */
        validate : function(formE) { //扩展方法
        	var options = {};
        	options = getExtendSettings(formE, options); 
            return formE.kvvalid(options);
        }
    }
    /** 加载中的html代码
    @type String
    */
    ,loadingHtml:"加载中……"
    /** 头部信息区
        @type jQueryObject
    */
    ,topBarE : null
    /** 头部菜单区
        @type jQueryObject
    */
    ,topMenuE : null
    /** 选中的头部菜单区
        @type jQueryObject
    */
    ,activeTopMenuE : null
    /** 左侧栏
        @type jQueryObject
    */
    ,siderE : null
    /** 左侧栏选中区
        @type jQueryObject
    */
    ,activeSiderE : null
    /** 主内容区（不变）
        @type jQueryObject
    */
    ,contentMainE: null
    /** 当前可见的主内容区tab内容区
        @type jQueryObject
    */
    ,avtiveTabContentE : null
    /** 当前可见的主内容区tab标题
        @type jQueryObject
    */
    ,activeTabTitleE : null
    /** 弹出框 ，其他可在实现框架内扩展
        @type jQueryObject
    */
    ,dialogE : null
    /** shieldDialog回调方法
        @type Key-Value
    */
    ,shieldDialogCallback : {}
    /** 初始化扩展方法
        @param options 配置文件，参考shield.core.js的参数配置
        @see shield.core.js#_defaults
    */
    ,initExtend : function(options){
    }
    /** 初始化方法，使用时直接调用该方法
        @param options 配置文件，参考shield.core.js的参数配置
        @see shield.core.js#_defaults
    */
    ,init : function(options){ //
        this.initExtend(options);
        ShieldJS.core.main(options); 
    }
};
ShieldJS.getJsPath();
 
var request;
var clickBtn;
var abortLastReq = function() {
    if (request) {
        request.abort();
        request = null;
    }
};
//统一AJAX处理
$.ajaxSetup({
    //具体实现优先，没有具体实现时才调用该方法
    error : function(response, textStatus, errorThrown) {
        ShieldJS.ajax.global.error(response, textStatus, errorThrown);
        return false;
    },
    complete : function(response, textStatus) {
        ShieldJS.ajax.global.complete(response, textStatus);
    }
});
//button不可用
var disabledBtn = function() {
    if(ShieldJS.contentMainE && ShieldJS.contentMainE.length > 0){
        ShieldJS.contentMainE.find(":button:not(.ignoredis)").prop("disabled",true);
    }
    if(ShieldJS.dialogE && ShieldJS.dialogE.length > 0){
        ShieldJS.dialogE.find(":button:not(.ignoredis)").prop("disabled",true);
    }
};
//button恢复可用
var undisabledBtn = function() {
    if(ShieldJS.contentMainE && ShieldJS.contentMainE.length > 0){
        ShieldJS.contentMainE.find(":button:not(.ignoredis)").prop("disabled",false);
    }
    if(ShieldJS.dialogE && ShieldJS.dialogE.length > 0){
        ShieldJS.dialogE.find(":button:not(.ignoredis)").prop("disabled",false);
    }
};
//浏览器resize时调用方法
$(window).resize(function() {
    var actions = $.extend({},ShieldJS.winResizes);
    for(var actionName in actions){
        try {
            if ($.isFunction(actions[actionName])) {
                actions[actionName]();
            }
        } catch (e) {
            ShieldJS.error("resize方法异常："+actionName+" "+e);
            return false;
        }
    }
});
//document点击时调用方法，如点击空白关闭弹出层等
$(document).click(function() {
    var actions = $.extend({},ShieldJS.docClicks);
    for(var actionName in actions){
        try {
            if ($.isFunction(actions[actionName])) {
                actions[actionName]();
            }
        } catch (e) {
            ShieldJS.error("点击方法异常："+actionName+" "+e);
            return false;
        }
    }
});
